package mobilesmil.activity.composer;

import java.util.ArrayList;
import java.util.Random;

import mobilesmil.activity.FileBrowserActivity;
import mobilesmil.activity.PlayerActivity;
import mobilesmil.activity.R;
import mobilesmil.activity.SendActivity;
import mobilesmil.adapter.SmilResourceAdapter;
import mobilesmil.data.SmilDataSet;
import mobilesmil.data.SmilResource;
import mobilesmil.xml.generating.SmilXmlGenerator;
import mobilesmil.xml.parsing.SmilParser;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
/**
 * Provides list of {@link SmilResource}s in the {@link SmilDataSet} that is currently being edited by the user.
 * The user is able to edit every aspect of the {@link SmilDataSet} from here - from the properties of individual
 * resources to the positioning of the {@link SmilRegion}s associated with them.
 * @author Ryan Ware
 *
 */
public class ComposerActivity extends ListActivity {
	private static final byte MENU_ADD_RESOURCE = 0;
	private static final byte MENU_SAVE = 1;
	private static final byte MENU_OPEN = 2;
	private static final byte MENU_PREVIEW = 3;
	private static final byte MENU_EDIT_GENERAL_PROPS = 4;
	private static final byte MENU_SEND = 5;
	
	private static final byte DIALOG_EXCEPTION_ID = 0;
	private static final byte DIALOG_SAVE_ID = 1;
	private static final byte DIALOG_DELETE_RESOURCE_ID = 2;
	
	public static final byte REQUEST_CODE_GENERAL_PROPERTIES = 0;
	public static final byte REQUEST_CODE_ADD_NEW_RESOURCE = 1;
	public static final byte REQUEST_CODE_RESOURCE_PROPERTIES = 2;
	public static final byte REQUEST_CODE_POSITION_RESOURCE = 3;
	public static final byte REQUEST_CODE_OPEN = 4;
	
	public static final byte RESULT_CODE_POSITION = 1;
	public static final byte RESULT_CODE_DELETE = 2;
	public static final byte RESULT_CODE_NEW_BACK_BUTTON = 3;
	
	public static final String DIALOG_EXCEPTION_TITLE = "Oops!";
	private static String mDialogExceptionMessage;
	private static SmilDataSet mEditingDataSet;
	private static SmilResource mEditingResource;
	private static String mNewResourceType;
	private static SmilResourceAdapter mAdapter;
	
	private static boolean mIsCreatingNewSmil = false;
	private static boolean mIsCreatingNewResource = false;
	private static boolean mIsSaved = true;
	private static int mIndexOfResourceToDelete;
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		String task = getIntent().getStringExtra(this.getString(R.string.composerTask));
		
		if(task.equals(this.getString(R.string.createNew))) { // creating a new SMIL
			getIntent().putExtra(this.getString(R.string.composerTask), this.getString(R.string.edit));
			beginCreatingNewSmil();
		}
		else if(task.equals(this.getString(R.string.edit))) { // editing existing SMIL
			String fileName = getIntent().getExtras().getString(this.getString(R.string.fileName));
    		openFileForEditing(fileName);
		}

	}
	/**
	 * Starts {@link AddNewResourceActivity} for result.
	 */
	private void openAddNewResourceActivity() {
		Intent newResourceIntent = new Intent(getApplicationContext(), AddNewResourceActivity.class);
		startActivityForResult(newResourceIntent, REQUEST_CODE_ADD_NEW_RESOURCE);
	}
	/**
	 * Starts {@link ResourcePropsFormActivity} for result.
	 */
	public void openResourcePropertiesActivity() {
		Intent resourcePropertiesIntent = new Intent(getApplicationContext(), ResourcePropsFormActivity.class);
		startActivityForResult(resourcePropertiesIntent, REQUEST_CODE_RESOURCE_PROPERTIES);
	}
	/**
	 * Starts {@link GeneralPropsFormActivity} for result.
	 */
	private void openGeneralPropertiesFormActivity() {
		Intent generalPropsIntent = new Intent(getApplicationContext(), GeneralPropsFormActivity.class);
		startActivityForResult(generalPropsIntent,REQUEST_CODE_GENERAL_PROPERTIES);
	}
	/**
	 * Starts {@link PlayerActivity} with Intent extra playerTask = preview.
	 */
	private void openPlayerActivityForPreview() {
		Intent playerIntent = new Intent(getApplicationContext(), PlayerActivity.class);
		playerIntent.putExtra(this.getString(R.string.playerTask), this.getString(R.string.preview));
		startActivity(playerIntent);
	}
	/**
	 * Starts {@link SendActivity} with Intent extra sendTask = send and fileName = mEditingDataSet.getFileName().
	 */
	private void openSendActivity() {
		Intent send = new Intent(getApplicationContext(), SendActivity.class);
		send.putExtra(this.getString(R.string.sendTask), this.getString(R.string.send));
		send.putExtra(this.getString(R.string.fileName), mEditingDataSet.getFileName());
		startActivity(send);
	}
	/**
	 * Generates a unique integer-valued {@link String} for use as a {@link SmilRegion} ID.
	 * @return {@link String} unique region ID
	 */
	public static String generateUniqueRegionId() {
		Random rand = new Random();
		String newRegionId = "";
		boolean unique = true;
		
		do {
			newRegionId = String.valueOf(rand.nextInt());
			
			for(SmilResource resource : mEditingDataSet.getResourcesByBeginTime())
			{
				if(resource.getSmilRegion().getId().equals(newRegionId)) {
					unique = false;
					break;
				}
			}
			
		} while(!unique);
		
		return newRegionId;
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
		super.onActivityResult(requestCode, resultCode, intent);
		Bundle properties = null;
		if(intent != null)
			properties = intent.getExtras();
		
		switch(requestCode)
		{
	        case REQUEST_CODE_GENERAL_PROPERTIES: // from GeneralPropsFormActivity
	        	switch(resultCode)
	        	{
	        	case RESULT_OK:
	        		if(mIsCreatingNewSmil)
			        	openAddNewResourceActivity();
			        else
			        	refreshExistingResourcesList();
			        break;
	        	case RESULT_CODE_NEW_BACK_BUTTON:
	        		finish();
			        break;
	        	}
	        	break;
		        
	        case REQUEST_CODE_ADD_NEW_RESOURCE: // from AddNewResourceActivity
	        	switch(resultCode)
	        	{
	        	case RESULT_OK:
	        		openResourcePropertiesActivity();
	        		break;
	        	case RESULT_CODE_NEW_BACK_BUTTON:
	        		openGeneralPropertiesFormActivity();
	        		break;
	        	}
	        	break;
	        	
	        case REQUEST_CODE_RESOURCE_PROPERTIES: // from ResourcePropsFormActivity
	        	switch(resultCode)
	        	{
		        	case RESULT_OK:
		        		refreshExistingResourcesList();
		        		break;
		        	case RESULT_CODE_NEW_BACK_BUTTON:
		        		openAddNewResourceActivity();
		        		break;
	        	}
	        	break;
	        	
	        case REQUEST_CODE_POSITION_RESOURCE: // from RegionPositioningActivity
	        	openResourcePropertiesActivity();
	        	break;
	        	
	        case REQUEST_CODE_OPEN:
	        	switch(resultCode)
	        	{
		        	case RESULT_OK:
		        		if(properties != null) {
		        			String fileName = properties.getString(this.getString(R.string.fileName));
		        			openFileForEditing(fileName);
		        		}
		        	break;
	        	}
	        break;
        }
    }
	/**
	 * Loads a SMIL file into the Composer for editing.
	 * @param fileName relative name of file to be opened in Composer
	 */
	private void openFileForEditing(String fileName) {
		SmilDataSet openedDataSet;
		try {
			openedDataSet = SmilParser.getParsedDataSet(fileName);
		} catch (Exception e) {
			mDialogExceptionMessage = "Cannot open file.";
			showDialog(DIALOG_EXCEPTION_ID);
			return;
		}
		mEditingDataSet = openedDataSet;
		mEditingResource = null;
		mNewResourceType = null;
		mIsCreatingNewSmil = false;
		mIsCreatingNewResource = false;
		mIsSaved = true;
		refreshExistingResourcesList();
	}
	/**
	 * Removes the {@link SmilResource} found at mIndexOfResourceToDelete of mEditingDataSet.getResourcesByBeginTime().
	 * Refreshes the Resources list.
	 */
	private void deleteResourceAtIndex() {
		if(mIndexOfResourceToDelete >= 0 && mEditingDataSet != null){
			SmilResource deletingResource = mEditingDataSet.getResourcesByBeginTime().get(mIndexOfResourceToDelete);
			mEditingDataSet.removeResource(deletingResource);
			mIndexOfResourceToDelete = -1;
			mEditingResource = null;
			mIsSaved = false;
			refreshExistingResourcesList();
		}
	}
	/**
	 * Adds a resource to mEditingDataSet.
	 * @param editingResource {@link SmilResource} to be added to mEditingDataSet.
	 */
	public static void addNewResource(SmilResource editingResource) {
		mEditingDataSet.addResource(editingResource);
	//	editingResource = null;
	//	newResourceType = null;
	}
	
	@Override
	protected Dialog onCreateDialog(int id) {
	    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
	    dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
	    switch(id) 
	    {
		    case DIALOG_EXCEPTION_ID: // notify user of a problem
		    	dialogBuilder.setTitle(DIALOG_EXCEPTION_TITLE);
		        dialogBuilder.setMessage(mDialogExceptionMessage);
		        dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
		          public void onClick(DialogInterface dialog, int which) {
		            finish();
		          } });
		    	break;
		    	
		    case DIALOG_SAVE_ID: // NOT USED
		    	dialogBuilder.setTitle("Would you like to save?");
		    	dialogBuilder.setPositiveButton("Yes", 
		    			new DialogInterface.OnClickListener() {
		    				public void onClick(DialogInterface dialog, int whichButton) {
		    					saveEditingDataSet();
		    				//	notifyAll();
		    					return;
		    			    }
		    	});
		    	dialogBuilder.setNegativeButton("No", 
		    			new DialogInterface.OnClickListener() {
		    				public void onClick(DialogInterface dialog, int whichButton) {
		    				//	notifyAll();
		    					return;
		    			    }
		    	});
		    	break;
		    	
		    case DIALOG_DELETE_RESOURCE_ID: // prompt user if they wish to delete resource
		    	dialogBuilder.setTitle("Remove resource?");
		    	dialogBuilder.setPositiveButton("Yes", 
		    			new DialogInterface.OnClickListener() {
		    				public void onClick(DialogInterface dialog, int whichButton) {
		    					deleteResourceAtIndex();
		    					return;
		    			    }
		    	});
		    	dialogBuilder.setNegativeButton("No", 
		    			new DialogInterface.OnClickListener() {
		    				public void onClick(DialogInterface dialog, int whichButton) {
		    					return;
		    			    }
		    	});
		    	break;
	    }
	    return dialogBuilder.create();
	}
	/**
	 * Sets boolean values to begin creating a new SMIL file and opens the {@link GeneralPropsFormActivity}.
	 */
	private void beginCreatingNewSmil() {
		mIsCreatingNewSmil = true;
		mIsCreatingNewResource = false;
		mEditingDataSet = new SmilDataSet();
		openGeneralPropertiesFormActivity();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, MENU_ADD_RESOURCE, 0, "Add Resource").setIcon(android.R.drawable.ic_menu_add);
		menu.add(0, MENU_EDIT_GENERAL_PROPS, 1, "Edit General Properties").setIcon(android.R.drawable.ic_menu_edit);
		menu.add(0, MENU_SAVE, 2, "Save").setIcon(android.R.drawable.ic_menu_save);
		menu.add(0, MENU_PREVIEW, 3, "Preview").setIcon(android.R.drawable.ic_menu_view);
		menu.add(0, MENU_SEND, 4, "Send").setIcon(android.R.drawable.ic_menu_send);
		menu.add(0, MENU_OPEN, 5, "Open").setIcon(android.R.drawable.ic_menu_upload);
		
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId())
		{
			case MENU_SAVE:
				saveEditingDataSet();
				break;
			case MENU_OPEN:
				if(!mIsSaved) {} //TODO: implement "Would you like to Save?" dialog
				Intent managerIntent = new Intent(getApplicationContext(), FileBrowserActivity.class);
				managerIntent.putExtra(this.getString(R.string.managerTask), this.getString(R.string.browse));
				startActivityForResult(managerIntent, REQUEST_CODE_OPEN);
				break;
			case MENU_PREVIEW:
				openPlayerActivityForPreview();
				break;
			case MENU_SEND:
				saveEditingDataSet();
				openSendActivity();
				break;
			case MENU_ADD_RESOURCE:
				openAddNewResourceActivity();
				break;
			case MENU_EDIT_GENERAL_PROPS:
				openGeneralPropertiesFormActivity();
				break;
		}
		
		return true;
	}
	
	

	@Override
	public void onBackPressed() {
		System.gc();
		finish();
	}

	/**
	 * Delete icon's OnClickListener, as specified in list_resources_row.xml.
	 * Prompts user if they wish to delete the selected {@link SmilResource}.
	 * @param resourceIndex index of resource to delete
	 */
	public void promptToDeleteResource(int resourceIndex) {
		mIndexOfResourceToDelete = resourceIndex;
		showDialog(DIALOG_DELETE_RESOURCE_ID);
	}

	/**
	 * Saves mEditingDataSet to the device's SD card directory.
	 */
	private void saveEditingDataSet() {
    	try {
    		SmilXmlGenerator.saveAsXML(mEditingDataSet);
    	} catch (Exception e) { // display exception dialog box
			mDialogExceptionMessage = "Cannot save file.";
			showDialog(DIALOG_EXCEPTION_ID);
			return;
    	}
    	mIsSaved = true;
    	Toast.makeText(getApplicationContext(), "Saved", Toast.LENGTH_SHORT).show(); // notify user it has been saved
	}
	
	/**
	 * Refreshes the list of {@link SmilResource}s to recognize any additions, deletions, or reordering.
	 */
	public void refreshExistingResourcesList() {
		mIsCreatingNewSmil = false;
		mIsCreatingNewResource = false;
		setContentView(R.layout.list_resources);
        ((TextView)findViewById(R.id.titleResourcesList)).setText(mEditingDataSet.getFileName());
        generateList(mEditingDataSet.getResourcesByBeginTime());
        ((Button)findViewById(R.id.btnAddResource)).setOnClickListener(addResourceListener);
        ((Button)findViewById(R.id.btnPreview)).setOnClickListener(btnPreviewListener);
	}
	
	private OnClickListener addResourceListener = new OnClickListener() {
		public void onClick(View view) {
			openAddNewResourceActivity();
		}
	};
	
	private OnClickListener btnPreviewListener = new OnClickListener() {
		public void onClick(View view) {
			openPlayerActivityForPreview();
		}
	};
	
	/**
	 * Creates new {@link SmilResourceAdapter} to display list of {@link SmilResource}s.
	 * @param resources {@link ArrayList}<{@link SmilResource}> to be displayed
	 */
	private void generateList(ArrayList<SmilResource> resources) {
    	resources = new ArrayList<SmilResource>();
        mAdapter = new SmilResourceAdapter(this, R.layout.list_resources_row, resources);
        
        setListAdapter(mAdapter);
        //this will allow for the background to show through when scrolling is happening
        getListView().setCacheColorHint(Color.TRANSPARENT);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
            	ArrayList<SmilResource> resources = mEditingDataSet.getResourcesByBeginTime();
                if(resources != null && resources.size() > 0)
                {
                    mAdapter.notifyDataSetChanged();
                    for(int i=0;i<resources.size();i++) 
                    {
                    	mAdapter.add(resources.get(i));
                    }
                }
                mAdapter.notifyDataSetChanged();
            }
        });
    }
   
    @Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		setEditingResource(mEditingDataSet.getResourcesByBeginTime().get(position));
		openResourcePropertiesActivity();
	}
    /**
     * Removes and re-adds mEditingResource to mEditingDataSet so the order of {@link SmilResource}s
     * in the {@link SmilDataSet}'s resource lists is updated.
     */
    public static void refreshDataSet() {
		mEditingDataSet.removeResource(mEditingResource);
		mEditingDataSet.addResource(mEditingResource);
	}
    
	public static SmilDataSet getEditingDataSet() {
		return mEditingDataSet;
	}

	public static SmilResource getEditingResource() {
		return mEditingResource;
	}

	protected static void setEditingResource(SmilResource editingResource) {
		ComposerActivity.mEditingResource = editingResource;
	}

	protected static String getNewResourceType() {
		return mNewResourceType;
	}

	protected static void setNewResourceType(String newResourceType) {
		ComposerActivity.mNewResourceType = newResourceType;
	}

	public static boolean isCreatingNewSmil() {
		return mIsCreatingNewSmil;
	}
	
	public static void setCreatingNewSmil(boolean isCreatingNewSmil) {
		ComposerActivity.mIsCreatingNewSmil = isCreatingNewSmil;
	}

	public static void setCreatingNewResource(boolean isCreatingNewResource) {
		ComposerActivity.mIsCreatingNewResource = isCreatingNewResource;
	}
	
	public static boolean isCreatingNewResource() {
		return mIsCreatingNewResource;
	}

}